#!/bin/bash

# 配置参数
MONITOR_INTERVAL=10  # 监控间隔(秒)
MONITOR_CYCLES=6     # 监控周期数
MEM_GROWTH_THRESHOLD=20  # 内存增长百分比阈值
MEM_ABSOLUTE_THRESHOLD=100  # 触发限制的绝对内存阈值(MB)
DEFAULT_MEM_LIMIT_RATIO=1.5  # 默认限制值为峰值内存的倍数
PERSISTENT_MODE=true  # 默认使用持久化配置

# 安装必要工具
check_dependencies() {
    if ! command -v smem &>/dev/null; then
        echo "[安装] 安装内存分析工具smem..."
        apt-get -qq install smem >/dev/null 2>&1 || yum -q install smem >/dev/null 2>&1
    fi
}

# 获取服务的内存使用(MB)
get_service_memory() {
    local service=$1
    smem -P "/$service" -c "service rss" -k -t -U root | \
        awk -v service="$service" '$1 == service {print $2}'
}

# 监控服务内存变化
monitor_memory_usage() {
    declare -A mem_start mem_end mem_history
    
    echo -e "\n[阶段1] 检测高内存消耗服务 (${MONITOR_CYCLES}周期 x ${MONITOR_INTERVAL}秒)"
    echo "---------------------------------------------"
    
    # 初始读数
    for service in $(systemctl list-units --type=service --no-legend | awk '{print $1}'); do
        mem_start[$service]=$(get_service_memory "${service%.*}")
    done
    
    # 监控周期
    for ((i=1; i<=MONITOR_CYCLES; i++)); do
        echo -n "周期 $i/$MONITOR_CYCLES: "
        for service in "${!mem_start[@]}"; do
            current_mem=$(get_service_memory "${service%.*}")
            [[ -n "$current_mem" ]] || continue
            
            # 记录历史峰值
            if [[ -z ${mem_history[$service]} ]] || (( $(echo "$current_mem > ${mem_history[$service]}" | bc -l) )); then
                mem_history[$service]=$current_mem
            fi
            
            # 显示状态
            if (( $(echo "$current_mem > 100" | bc -l) )); then
                echo -n "${service%.*}:${current_mem%.*}MB "
            fi
        done
        echo ""
        sleep "$MONITOR_INTERVAL"
    done
    
    # 最终读数
    for service in "${!mem_start[@]}"; do
        mem_end[$service]=$(get_service_memory "${service%.*}")
    done
    
    # 分析增长趋势
    echo -e "\n[分析] 检测到以下服务内存持续增长:"
    local detected=0
    for service in "${!mem_start[@]}"; do
        start_val=${mem_start[$service]}
        end_val=${mem_end[$service]}
        [[ -z "$start_val" || -z "$end_val" ]] && continue
        
        # 计算增长率
        growth=$(echo "scale=2; ($end_val - $start_val) * 100 / $start_val" | bc -l 2>/dev/null)
        [[ -z "$growth" ]] && continue
        
        # 应用检测逻辑
        if (( $(echo "$growth > $MEM_GROWTH_THRESHOLD" | bc -l) )) && \
           (( $(echo "$end_val > $MEM_ABSOLUTE_THRESHOLD" | bc -l) )); then
            echo "  - $service: ${start_val%.*}MB → ${end_val%.*}MB (+${growth%.*}%)"
            candidates+=("$service:${mem_history[$service]}:$growth")
            ((detected++))
        fi
    done
    
    if [[ $detected -eq 0 ]]; then
        echo "  [信息] 未检测到显著内存增长的服务"
        echo " 已经自动清理可疑服务 "
        exit 0
    fi
}

# 应用内存限制
apply_memory_limit() {
    local service=$1
    local peak_mem=$2
    local growth=$3
    
    # 计算限制值 (峰值内存 * 安全系数)
    limit_value=$(echo "scale=0; $peak_mem * $DEFAULT_MEM_LIMIT_RATIO / 1" | bc)
    [[ $limit_value -lt 200 ]] && limit_value=200  # 最小200MB
    human_limit="${limit_value}M"
    
    echo -e "\n[调优] 应用内存限制到 $service:"
    echo "  - 历史峰值: ${peak_mem%.*}MB"
    echo "  - 增长率: +${growth%.*}%"
    echo "  - 设置限制: $human_limit"
    
    # 应用限制
    if $PERSISTENT_MODE; then
        conf_dir="/etc/systemd/system/${service}.d"
        mkdir -p "$conf_dir"
        conf_file="${conf_dir}/memory_leak_protection.conf"
        
        echo "[Service]" > "$conf_file"
        echo "MemoryMax=$human_limit" >> "$conf_file"
        echo "MemoryHigh=$(echo "scale=0; $limit_value * 0.8" | bc)M" >> "$conf_file"
        
        systemctl daemon-reload
        echo "  - 持久化配置: $conf_file"
    else
        systemctl set-property "$service" MemoryMax="$human_limit"
        systemctl set-property "$service" MemoryHigh="$(echo "scale=0; $limit_value * 0.8" | bc)M"
    fi
    
    # 重启服务
    echo "  - 重启服务使配置生效..."
    systemctl restart "$service" 2>/dev/null
    
    # 验证
    echo -e "\n[验证] 当前内存限制:"
    systemctl show -p MemoryMax,MemoryHigh "$service" | grep -E 'Memory(Max|High)'
}

# 主程序
check_dependencies
declare -a candidates

monitor_memory_usage

echo -e "\n[阶段2] 自动应用内存限制"
echo "---------------------------------------------"

for candidate in "${candidates[@]}"; do
    IFS=':' read -r service peak_mem growth <<< "$candidate"
    
    # 获取服务状态
    status=$(systemctl is-active "$service" 2>/dev/null)
    if [[ "$status" != "active" ]]; then
        echo "  [跳过] 服务未运行: $service"
        continue
    fi
    
    # 检查是否已设置限制
    current_limit=$(systemctl show -p MemoryMax "$service" | cut -d= -f2)
    if [[ "$current_limit" != "infinity" ]]; then
        echo "  [跳过] 已存在内存限制: $service ($current_limit)"
        continue
    fi
    
    # 应用限制
    apply_memory_limit "$service" "$peak_mem" "$growth"
done

echo -e "\n[完成] 资源泄露防护已配置"
echo "---------------------------------------------"
echo "后续操作建议:"
echo "1. 监控服务状态: systemctl status <服务名>"
echo "2. 查看内存限制: systemctl show -p MemoryMax <服务名>"
echo "3. 查看cgroup状态: cat /sys/fs/cgroup/system.slice/$(systemd-escape \"<服务名>\")/memory.max"
echo "4. 如需调整限制: 编辑 /etc/systemd/system/<服务名>.d/memory_leak_protection.conf"